package com.weilele.mvvm.utils.thread

import android.os.AsyncTask

/**
 * 用AsyncTask代替线程，减少消耗
 * 虽然创建多个对象，但是他自己会用一个线程池
 * 一个对象只是一个任务
 */
class AsyncThread<Params, Progress, Result>(
        private val isSerial: Boolean = false/*是否按顺序一个一个执行任务*/,
        private val call: AsyncThreadCall<Progress, Result>? = null,
        private val run: (params: Array<out Params>) -> Result
) : AsyncTask<Params, Progress, Result>() {
    /**
     * 是否运行过
     */
    private var isHadRun = false

    override fun onProgressUpdate(values: Array<Progress>) {
        super.onProgressUpdate(*values)
        call?.onProgressUpdate(values)
    }

    override fun onPostExecute(result: Result) {
        super.onPostExecute(result)
        call?.onComplete(result)
    }

    override fun doInBackground(params: Array<out Params>): Result {
        return run.invoke(params)
    }

    override fun onCancelled(result: Result) {
        super.onCancelled(result)
        call?.onCancelled(result)
    }

    override fun onCancelled() {
        super.onCancelled()
        call?.onCancelled()
    }

    override fun onPreExecute() {
        super.onPreExecute()
        call?.onStart()
    }

    fun onError(error: Throwable) {
        call?.onError(error)
    }

    /**
     * 设置进度@{onProgressUpdate}会回调
     */
    fun setProgress(vararg progress: Progress) {
        publishProgress(*progress)
        call?.onProgressUpdateInIoThread(progress)
    }

    /**
     * 开启线程
     */
    fun start(vararg values: Params): AsyncTask<Params, Progress, Result> {
        if (isHadRun) {
            //AsyncTask只能运行一次，否则会报错
            return this
        }
        isHadRun = true
        return if (isSerial) {
            execute(*values)
        } else {
            executeOnExecutor(THREAD_POOL_EXECUTOR, *values)
        }
    }

    interface AsyncThreadCall<Progress, Result> {
        fun onProgressUpdate(values: Array<out Progress>) {
        }

        fun onProgressUpdateInIoThread(values: Array<out Progress>) {
        }

        fun onComplete(result: Result) {
        }

        fun onCancelled(result: Result) {
        }

        fun onCancelled() {
        }

        fun onError(error: Throwable) {

        }

        fun onStart() {
        }
    }
}